package com.smart.upms.sys.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Sets;
import com.smart.core.starter.utils.CopyUtils;
import com.smart.core.starter.utils.PasswordUitl;
import com.smart.upms.constant.CacheConstant;
import com.smart.upms.sys.entity.SysUser;
import com.smart.upms.sys.entity.SysUserRole;
import com.smart.upms.sys.mapper.SysMenuMapper;
import com.smart.upms.sys.mapper.SysRoleMapper;
import com.smart.upms.sys.mapper.SysUserMapper;
import com.smart.upms.sys.mapper.SysUserRoleMapper;
import com.smart.upms.sys.param.SysUserParam;
import com.smart.upms.sys.param.SysUserQueryParam;
import com.smart.upms.sys.result.SysMenuResult;
import com.smart.upms.sys.result.SysRoleResult;
import com.smart.upms.sys.result.SysUserAndRoleResult;
import com.smart.upms.sys.result.SysUserResult;
import com.smart.upms.sys.result.UserInfoResult;
import com.smart.upms.sys.service.ISysUserService;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 系统用户 服务实现类
 * </p>
 *
 * @author guxiaobai
 * @since 2018-12-05
 */
@Service
@AllArgsConstructor
public class SysUserServiceImpl implements ISysUserService {

    private final SysUserMapper mapper;
    private final SysRoleMapper roleMapper;
    private final SysMenuMapper menuMapper;
    private final SysUserRoleMapper userRoleMapper;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean save(SysUserParam param) {
        SysUser entity = CopyUtils.copyObject(param, SysUser.class);
        entity.setPassword(PasswordUitl.password(entity.getPassword()));
        int insert = mapper.insert(entity);
        updateUserRole(param, entity);
        return insert > 0;
    }


    @Override
    @CacheEvict(value = CacheConstant.CacheUser.USER_DETAILS, key = "#param.username")
    public Boolean update(SysUserParam param) {
        SysUser entity = CopyUtils.copyObject(param, SysUser.class);
        entity.setPassword(PasswordUitl.password(entity.getPassword()));
        int update = mapper.updateById(entity);
        QueryWrapper<SysUserRole> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(SysUserRole.USER_ID, param.getId());
        userRoleMapper.delete(queryWrapper);
        updateUserRole(param, entity);
        return update > 0;

    }

    @Override
    @CacheEvict(value = CacheConstant.CacheUser.USER_DETAILS, key = "#user.username")
    public Boolean delete(SysUserResult user) {
        int delete = mapper.deleteById(user.getId());
        return delete > 0;
    }

    @Override
    public SysUserResult get(Long id) {
        SysUser entity = mapper.selectById(id);
        return CopyUtils.copyObject(entity, SysUserResult.class);
    }

    @Override
    public List<SysUserResult> list(SysUserQueryParam param) {
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
        List<SysUser> entityList = mapper.selectList(queryWrapper);
        return CopyUtils.copyList(entityList, SysUserResult.class);
    }

    @Override
    public Page<SysUserAndRoleResult> listPage(Page<SysUserAndRoleResult> page, SysUserQueryParam param) {
        page.setRecords(mapper.listPage(page, param));
        return page;
    }

    @Override
    @Cacheable(value = CacheConstant.CacheUser.USER_DETAILS, key = "#username", unless = "#result == null")
    public UserInfoResult infoByUsername(String username) {
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(SysUser.USERNAME, username);
        SysUser sysUser = mapper.selectOne(queryWrapper);
        if (sysUser != null) {
            UserInfoResult userInfoResult = new UserInfoResult();
            userInfoResult.setUserResult(CopyUtils.copyObject(sysUser, SysUserResult.class));
            //设置角色列表
            List<SysRoleResult> sysRoleResultList = roleMapper.findRolesByUserId(sysUser.getId());
            List<String> roleCodes = sysRoleResultList.stream().map(SysRoleResult::getRoleCode).collect(Collectors.toList());
            userInfoResult.setRoles(roleCodes);
            //设置权限列表（menu.permission）
            Set<String> permissions = Sets.newHashSet();
            roleCodes.forEach(role -> {
                List<SysMenuResult> sysMenuResultList = menuMapper.findByRoleCode(role);
                List<String> permissionList = sysMenuResultList.stream()
                        .filter(menuResult -> StringUtils.isNotEmpty(menuResult.getPermission()))
                        .map(SysMenuResult::getPermission).collect(Collectors.toList());
                permissions.addAll(permissionList);
            });
            userInfoResult.setPermissions(CollectionUtil.newArrayList(permissions));
            return userInfoResult;
        } else {
            return null;
        }


    }

    @Override
    public SysUserAndRoleResult getUserAndRole(Long id) {
        return mapper.getUserAndRole(id);

    }

    private void updateUserRole(SysUserParam param, SysUser entity) {
        param.getRoleIds().forEach(roleId -> {
            SysUserRole userRole = new SysUserRole();
            userRole.setUserId(entity.getId());
            userRole.setRoleId(roleId);
            userRoleMapper.insert(userRole);
        });
    }
}
